﻿#include "pch.h"
#include "hid_encoder.h"
#include "crc/crcLib.h"
#include "callback.h"
#include "code.h"
#include "utils/packutils.h"
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

/**
 * 构造函数
 * @brief hid_encoder::hid_encoder
 * @param hidInterface
 * @param pool
 * @param cfg
 */
hid_encoder::hid_encoder(std::shared_ptr<hid_interface> _hid_interface,
                         std::shared_ptr<config> _cfg)
    : hidInterface(_hid_interface), threadPool(std::make_unique<ThreadPool>(1)),
      cfg(_cfg) {}

hid_encoder::~hid_encoder() {
  std::cout << "hid_encoder::~hid_encoder() " << std::endl;
}

/**
 * 异步写数据
 * @brief hid_encoder::writeData
 * @param data      数据
 * @param size      数据长度
 * @param tag       标签
 * @param tagSize   标签长度
 * @param cmd       命令
 * @param l         写数据监听
 * @return
 */
void hid_encoder::writeData(const char *data, int size, const char *tag,
                            int tagSize, char cmd,
                            std::weak_ptr<OnHIDWriteListener> writeListener) {

  std::lock_guard<std::mutex> lock(g_Mutex);
  if (isRunning.load()) {
#ifdef _DEBUG
    std::cout << "HID BUSY...." << std::endl;
#endif
    std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
    if (l != nullptr) {
      l->onHIDWriteFailed(BUSY, "The HID bus busy. ");
    }
    return;
  }

#ifdef _DEBUG
  std::cout << "writeData enter...." << std::endl;
#endif

  threadPool->enqueue([this, data, size, tag, tagSize, cmd, writeListener] {
    std::unique_ptr<char[]> _tag(new char[tagSize]);
    if (_tag == nullptr) {
      release();
      std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
      if (l != nullptr) {
        l->onHIDWriteFailed(HID_WRITE_ERROR, "contentLength is 0.");
      }
      return;
    }

    std::fill(_tag.get(), _tag.get() + tagSize, 0);
    std::memcpy(_tag.get(), tag, tagSize);
    try {
      int contentLength = size;
      if (contentLength == 0) {
        release();
        std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
        if (l != nullptr) {
          l->onHIDWriteFailed(HID_WRITE_ERROR, "contentLength is 0.");
        }
        return;
      }

      // 开始处理数据
      isRunning.store(true);

      // 有效内容长度 （减去包头、附加信息）
      int requestBodyLength = getRequestBodyLength(true, tagSize);
      // 计算包个数
      long packageCount = getTotalPackCount(contentLength, requestBodyLength);

      // 输出dst
      std::vector<char> dst;
      // 记录发送的总包长度
      int totalPackageLength = 0;
      // 当前包索引
      int currentPackageIndex = 0;
      for (int i = 0; i < packageCount; i++) {
        // 中断包传输
        if (interrupt.load()) {
          release();
          std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
          if (l != nullptr) {
            l->onHIDWriteFailed(HID_WRITE_ERROR, "HID Write Error.");
          }

          // 通知中途停止
          std::shared_ptr<OnHIDStopDataListener> stopListener =
              stopListenerPtr.lock();
          if (stopListener != nullptr) {
            stopListener->onHIDStopData();
          }
          return;
        }

        // 2. 计算包长并拷贝数据
        if (i == packageCount - 1) {
          // 最后一个包剩余长度
          long remainCount = contentLength - totalPackageLength;

          // 1. 填充包头
          fillHead(dst, cmd, contentLength, remainCount, tagSize);
          if (tag != nullptr) {
            dst.insert(dst.end(), tag, tag + tagSize);
          }

          // 2. 填充包体
          dst.insert(dst.end(), data + totalPackageLength,
                     data + contentLength);

          // 3. 计算并填充 CRC
          int startIndex = getPackageContentStart(true, tagSize);
          std::vector<char> crc(dst.begin() + startIndex,
                                dst.begin() + startIndex + requestBodyLength);
          uint16_t crcIbm =
              crc16_ibm1((uint8_t *)crc.data(), (uint16_t)crc.size());
          dst.push_back(crcIbm);
          dst.push_back(crcIbm >> 8);
        } else {
          // 1. 填充包头
          fillHead(dst, cmd, contentLength, requestBodyLength, tagSize);
          if (tag != nullptr) {
            dst.insert(dst.end(), tag, tag + tagSize);
          }

          // 2. 填充包体
          dst.insert(dst.end(), data + totalPackageLength,
                     data + totalPackageLength + requestBodyLength);

          // 3. 计算并填充 CRC
          int startIndex = getPackageContentStart(true, tagSize);
          std::vector<char> crc(dst.begin() + startIndex,
                                dst.begin() + startIndex + requestBodyLength);
          uint16_t crcIbm =
              crc16_ibm1((uint8_t *)crc.data(), (uint16_t)crc.size());
          dst.push_back(crcIbm);
          dst.push_back(crcIbm >> 8);
        }

        // 魔数
        dst.push_back(JING_CHAR);
        dst.push_back(YUAN_YU_CHAR);
        dst.push_back(YUAN_YU_CHAR);

        // 下一个包截取的位置
        totalPackageLength += requestBodyLength;

        // 调用写数据接口，对数据进行1024对齐，末尾用 0x00 填充
        uint alignmentCount = ALLOW_LENGTH - dst.size();
        if (alignmentCount > 0) {
          dst.insert(dst.end(), alignmentCount, 0);
        }

        // 写数据
        if (this->write(dst.data(), ALLOW_LENGTH) == -1) {
          release();
          std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
          if (l != nullptr) {
            l->onHIDWriteFailed(HID_WRITE_ERROR, "HID Write Error.");
          }
          return;
        }

        currentPackageIndex++;
        std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
        if (l != nullptr) {
          l->onHIDWriteResult(currentPackageIndex, packageCount,
                              currentPackageIndex >= packageCount);
        }

        dst.resize(0);
      }
    } catch (std::exception &e) {
      std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
      if (l != nullptr) {
        l->onHIDWriteFailed(HID_WRITE_ERROR, "HID Write Error");
      }
    }

    release();

#ifdef _DEBUG
    std::cout << "writeData exit...." << std::endl;
#endif
  });
}

/**
 * 同步写数据
 * @brief hid_encoder::writeData
 * @param data
 * @param size
 * @param tag
 * @param tagSize
 * @param cmd
 * @return
 */
bool hid_encoder::writeDataSync(const char *data, int size, const char *tag,
                                int tagSize, char cmd) {
  std::lock_guard<std::mutex> lock(g_Mutex);
#ifdef _DEBUG
  std::cout << "writeDataSync enter...." << std::endl;
#endif
  if (isRunning.load()) {
    return false;
  }

  try {
    isRunning.store(true);
    int contentLength = size;
    if (contentLength == 0) {
      release();
      return false;
    }
    // 有效内容长度 （减去包头、附加信息）
    int requestBodyLength = getRequestBodyLength(true, tagSize);
    // 计算包个数
    long packageCount = getTotalPackCount(contentLength, requestBodyLength);

    // 输出dst
    std::vector<char> dst;
    // 记录发送的总包长度
    int totalPackageLength = 0;
    for (int i = 0; i < packageCount; i++) {
      // 中断传输
      if (interrupt.load()) {
        release();
        std::shared_ptr<OnHIDStopDataListener> stopListener =
            stopListenerPtr.lock();
        if (stopListener != nullptr) {
          stopListener->onHIDStopData();
        }
        return false;
      }

      // 2. 计算包长并拷贝数据
      if (i == packageCount - 1) {
        // 最后一个包剩余长度
        long remainCount = contentLength - totalPackageLength;

        // 1. 填充包头
        fillHead(dst, cmd, contentLength, remainCount, tagSize);
        if (tagSize != 0) {
          dst.insert(dst.end(), tag, tag + tagSize);
        }

        // 2. 填充包体
        dst.insert(dst.end(), data + totalPackageLength, data + contentLength);

        // 3. 计算并填充 CRC
        int startIndex = getPackageContentStart(true, tagSize);
        std::vector<char> crc;
        crc.assign(dst.begin() + startIndex,
                   dst.begin() + startIndex + remainCount);

        uint16_t crcIbm =
            crc16_ibm1((uint8_t *)crc.data(), (uint16_t)crc.size());
        dst.push_back(crcIbm);
        dst.push_back(crcIbm >> 8);
      } else {
        // 1. 填充包头
        fillHead(dst, cmd, contentLength, requestBodyLength, tagSize);
        if (tagSize != 0) {
          dst.insert(dst.end(), tag, tag + tagSize);
        }

        // 2. 填充包体
        dst.insert(dst.end(), data + totalPackageLength,
                   data + totalPackageLength + requestBodyLength);

        // 3. 计算并填充 CRC
        int startIndex = getPackageContentStart(true, tagSize);
        std::vector<char> crc(dst.begin() + startIndex,
                              dst.begin() + startIndex + requestBodyLength);
        uint16_t crcIbm =
            crc16_ibm1((uint8_t *)crc.data(), (uint16_t)crc.size());
        dst.push_back(crcIbm);
        dst.push_back(crcIbm >> 8);
      }

      // 魔数
      dst.push_back(JING_CHAR);
      dst.push_back(YUAN_YU_CHAR);
      dst.push_back(YUAN_YU_CHAR);

      // 下一个包截取的位置
      totalPackageLength += requestBodyLength;

      // 调用写数据接口，对数据进行1024对齐，末尾用 0x00 填充
      uint alignmentCount = ALLOW_LENGTH - dst.size();
      if (alignmentCount > 0) {
        dst.insert(dst.end(), alignmentCount, 0);
      }

      // 写数据
      if (this->write(dst.data(), ALLOW_LENGTH) == -1) {
        release();
        return false;
      }
      dst.resize(0);
    }
  } catch (std::exception &e) {
    release();
    return false;
  }

#ifdef _DEBUG
  std::cout << "writeDataSync exit...." << std::endl;
#endif

  release();

  return true;
}

/**
 * 写随机文件
 * @param filePath
 * @param tag
 * @param tagSize
 * @param l
 */
void hid_encoder::writeRandomFile(
    const string &filePath, int fileExtension,
    std::weak_ptr<OnHIDWriteRandomFileListener> writeRandomFileListener) {
  std::lock_guard<std::mutex> lock(g_Mutex);
  if (isRunning.load()) { // 禁止重复写，必须等待业务写完
#ifdef _DEBUG
    std::cout << "HID BUSY...." << std::endl;
#endif
    std::shared_ptr<OnHIDWriteRandomFileListener> l =
        writeRandomFileListener.lock();
    if (l != nullptr) {
      l->onHIDWriteRandomFailed(BUSY, "The HID bus busy. ");
    }
    return;
  }
  isRunning.store(true);

#ifdef _DEBUG
  std::cout << "writeRandomFile enter...." << std::endl;
#endif

  threadPool->enqueue([&, filePath, fileExtension, writeRandomFileListener] {
    // 检查文件名是否存在
    if (filePath.empty()) {
      std::shared_ptr<OnHIDWriteRandomFileListener> l =
          writeRandomFileListener.lock();
      if (l != nullptr) {
        l->onHIDWriteRandomFailed(HID_ERR, "The file path not exists");
      }
      release();
      return;
    }

    // 以二进制的方式打开随机文件.
    FILE *file = fopen(filePath.c_str(), "rb");
    if (file == nullptr) {
      std::shared_ptr<OnHIDWriteRandomFileListener> l =
          writeRandomFileListener.lock();
      if (l != nullptr) {
        l->onHIDWriteRandomFailed(HID_WRITE_ERROR, "Open random file error.");
      }
      release();
      return;
    }

    mRandomTaskRunning = true;
    std::string tag("RandomFile");
    // tag.length() 不包括null字符
    // 这里获取到内容有效长度要减去文件索引的4字节，这是为了随机写入
    int requestBodyLength =
        (int)getRandomFileRequestBodyLength((int)tag.length());
    char *buffer = (char *)malloc(requestBodyLength);
    if (buffer == nullptr) {
      std::shared_ptr<OnHIDWriteRandomFileListener> l =
          writeRandomFileListener.lock();
      if (l != nullptr) {
        l->onHIDWriteRandomFailed(HID_WRITE_ERROR, "Open random file error.");
      }
      release();
      state = STOPPED;
      return;
    }

    // 开始写随机文件
    std::shared_ptr<OnHIDWriteRandomFileListener> l =
        writeRandomFileListener.lock();
    if (l != nullptr) {
      l->onHIDWriteRandomStart();
    }

    while (mRandomTaskRunning) {
      // 进入暂停时
      if (state == PAUSE) {
        // 仅发送一次暂停通知上位机
        if (flag) {
          flag = false;
          int size = requestBodyLength + FILE_POS_COUNT;
          char *temp = (char *)malloc(size);
          if (temp == nullptr) {
            if (l != nullptr) {
              l->onHIDWriteRandomFailed(HID_WRITE_ERROR,
                                        "Open random file error.");
            }
            free(buffer);
            release();
            return;
          }
          memset(temp, 0, size);
          bool ret = writeDataSync(temp, size, tag.c_str(), (int)tag.length(),
                                   CMD_RANDOM_FILE_PAUSED);
          if (!ret) {
            state = STOPPED; // 任务结束
            if (l != nullptr) {
              l->onHIDWriteRandomFailed(HID_WRITE_ERROR,
                                        "Open random file error.");
            }
            fclose(file);
            free(buffer);
            return;
          } else {
            state = PAUSED; // 进入已暂停状态.
          }
          free(temp);
        }

        // 释放CPU时间片
        std::this_thread::sleep_for(std::chrono::milliseconds(5000));
        continue;
      } else if (state == CANCEL) {
        // 取消上传
        int size = requestBodyLength + FILE_POS_COUNT;
        char *temp = (char *)malloc(requestBodyLength + FILE_POS_COUNT);
        if (temp == nullptr) {
          if (l != nullptr) {
            l->onHIDWriteRandomFailed(HID_WRITE_ERROR,
                                      "Open random file error.");
          }
          release();
          free(buffer);
          state = STOPPED;
          return;
        }
        memset(temp, 0, size);
        bool ret = writeDataSync(temp, size, tag.c_str(), (int)tag.length(),
                                 CMD_RANDOM_FILE_CANCEL);
        if (!ret) {
          if (l != nullptr) {
            l->onHIDWriteRandomFailed(HID_WRITE_ERROR,
                                      "Open random file error.");
          }
          fclose(file);
        }
        free(temp);
        free(buffer);
        state = STOPPED;
        return;
      }

#ifdef _DEBUG
      std::cout << "准备跳过 " << pos << "字节" << std::endl;
#endif

      // 设置文件指针到 pos 位置
      if (fseek(file, pos, SEEK_SET) != 0) {
        fclose(file);
        release();
        if (l != nullptr) {
          l->onHIDWriteRandomFailed(HID_WRITE_ERROR,
                                    "Write random file error.");
        }
        state = STOPPED;
        free(buffer);
        return;
      }

      // 读取指定长度数据，这里是减去了文件索引的4字节数据
      size_t len = fread(buffer, sizeof(char), requestBodyLength, file);
      // 读取到数据
      if (len > 0) {
        // 加上文件偏移指针4字节，为实际内容长度
        int size = (int)(len + FILE_POS_COUNT);
        char *temp = (char *)malloc(size);
        if (temp == nullptr) {
          if (l != nullptr) {
            l->onHIDWriteRandomFailed(HID_WRITE_ERROR,
                                      "Open random file error.");
          }
          release();
          free(buffer);
          state = STOPPED;
          return;
        }
        // 先拷贝文件偏移指针
        char filePosBytes[FILE_POS_COUNT] = {0};
        if (pos > 0) {
          filePosBytes[0] = pos;
          filePosBytes[1] = pos >> 8;
          filePosBytes[2] = pos >> 16;
          filePosBytes[3] = pos >> 24;
        }
        memset(temp, 0, size);
        memcpy(temp, filePosBytes, FILE_POS_COUNT);
        memcpy(temp + FILE_POS_COUNT, buffer, len);
        int ret = writeDataSync(temp, size, tag.c_str(), (int)tag.length(),
                                CMD_RANDOM_FILE_START);
        if (!ret) {
          fclose(file);
          release();
          if (l != nullptr) {
            l->onHIDWriteRandomFailed(HID_WRITE_ERROR,
                                      "Write random file error.");
          }
          state = STOPPED;
          free(buffer);
          return;
        }
        free(temp);
      } else {
        if (feof(file)) {
          // 处理到达文件末尾的情况
          if (state == STOP || state == RESUMED) {
#ifdef _DEBUG
            std::cout << "文件已经写完...." << std::endl;
#endif
            // 数据已经读取完成
            break;
          }
          std::this_thread::sleep_for(std::chrono::milliseconds(1000));
          continue;
        } else {
          // 文件读取错误
          fclose(file);
          release();
          if (l != nullptr) {
            l->onHIDWriteRandomFailed(HID_WRITE_ERROR,
                                      "Write random file error.");
          }
          state = STOPPED;
          free(buffer);
          return;
        }
      }
    }

    // loop end...
    // 文件类型为 MP4，需要冲刷包
    if (fileExtension == MP4_LIVE) {
      // 外部中断停止发送
      index = 0;
      pos = 0;
      fseek(file, 0, SEEK_END);
      long contentLength = ftell(file);
      fseek(file, 0, SEEK_SET);

      // 重传前面的包，当传入实时视频文件时，前面的包中不包含有效长度，因此需要重刷下包
      int retransmitPacket = (int)(contentLength / requestBodyLength) + 1;
      int count = min(mRetransmitPacket, retransmitPacket);
      while (index <= count) {
        // 设置文件指针位置
        if (fseek(file, pos, SEEK_SET) != 0) {
          fclose(file);
          release();
          if (l != nullptr) {
            l->onHIDWriteRandomFailed(HID_WRITE_ERROR,
                                      "Write random file error.");
          }
          state = STOPPED;
          free(buffer);
          return;
        }

        size_t len = fread(buffer, sizeof(char), requestBodyLength, file);
        if (len > 0) {
          char filePosBytes[FILE_POS_COUNT] = {0};
          if (pos > 0) {
            filePosBytes[0] = pos;
            filePosBytes[1] = pos >> 8;
            filePosBytes[2] = pos >> 16;
            filePosBytes[3] = pos >> 24;
          }
          int dataSize = (int)(len + FILE_POS_COUNT);
          char *temp = (char *)malloc(dataSize);
          if (temp == nullptr) {
            fclose(file);
            release();
            if (l != nullptr) {
              l->onHIDWriteRandomFailed(HID_WRITE_ERROR,
                                        "Write random file error.");
            }
            state = STOPPED;
            free(buffer);
            return;
          }
          memset(temp, 0, dataSize);
          memcpy(temp, filePosBytes, FILE_POS_COUNT);
          memcpy(temp + FILE_POS_COUNT, buffer, len);
          int ret = writeDataSync(temp, dataSize, tag.c_str(),
                                  (int)tag.length(), CMD_RANDOM_FILE_START);
          if (!ret) {
            fclose(file);
            release();
            if (l != nullptr) {
              l->onHIDWriteRandomFailed(HID_WRITE_ERROR,
                                        "Write random file error.");
            }
            state = STOPPED;
            free(buffer);
            return;
          } else {
            pos += (int)len;
            index++;
          }
          free(temp);
        } else {
          if (feof(file)) {
            fclose(file);
            release();
            if (l != nullptr) {
              l->onHIDWriteRandomCompleted();
            }
            break;
          } else {
            fclose(file);
            release();
            if (l != nullptr) {
              l->onHIDWriteRandomFailed(HID_WRITE_ERROR,
                                        "Write random file error.");
            }
            state = STOPPED;
            free(buffer);
            return;
          }
        }
      }
    }

    // 写数据包结束帧，带上文件名
    // 重刷包结束，需要写入文件尾部
    size_t dotPos = filePath.rfind('.');
    if (dotPos == std::string::npos) {
      fclose(file);
      if (l != nullptr) {
        l->onHIDWriteRandomFailed(HID_ENCODE_ERROR,
                                  "The filePath must be absolute path.");
      }
      release();
      state = STOPPED;
      free(buffer);
      return;
    }
    std::string extension = filePath.substr(dotPos);
    time_t timestamp = time(NULL);
    std::tm *timeInfo = std::localtime(&timestamp);
    std::ostringstream oss;
    oss << std::put_time(timeInfo,
                         "%Y%m%d%H%M%S"); // 格式化为 YYYYMMDDHHMMSS
    std::string fileName = oss.str() + extension;
    int size = (int)(fileName.length() + FILE_NAME_COUNT);
    char *temp = (char *)malloc(size);
    if (temp == nullptr) {
      if (l != nullptr) {
        l->onHIDWriteRandomFailed(HID_WRITE_ERROR, "Open random file error.");
      }
      release();
      state = STOPPED;
      free(buffer);
      return;
    }
    // 拷贝文件名长度
    char fileNameLengthBytes[2] = {0};
    fileNameLengthBytes[0] = fileName.length();
    fileNameLengthBytes[1] = fileName.length() >> 8;

    memset(temp, 0, size);
    memcpy(temp, fileNameLengthBytes, 2);
    memcpy(temp + 2, fileName.c_str(), fileName.length());
    int ret = writeDataSync(temp, (int)(2 + fileName.length()), tag.c_str(),
                            (int)tag.length(), CMD_RANDOM_FILE_END);
    if (!ret) {
      fclose(file);
      release();
      isRunning = false;
      if (l != nullptr) {
        l->onHIDWriteRandomFailed(HID_WRITE_ERROR, "Write random file error.");
      }
      state = STOPPED;
      free(temp);
      free(buffer);
      return;
    }
    free(temp);

    // 任务结束
    state = STOPPED;

    if (l != nullptr) {
      l->onHIDWriteRandomCompleted();
    }

    free(buffer);
    buffer = nullptr;

#ifdef _DEBUG
    std::cout << "写随机文件退出...." << std::endl;
#endif
  });
}

/**
 * 异步写文件
 * @brief hid_encoder::writeFile
 * @param filePath  文件路径
 * @param tag       标签
 * @param tagSize   标签长度
 * @return
 */
void hid_encoder::writeFile(const std::string &filePath, const char *tag,
                            int tagSize) {
  this->writeFile(filePath, tag, tagSize, std::weak_ptr<OnHIDWriteListener>());
}

/**
 * 异步写文件
 * @brief hid_encoder::writeFile
 * @param filePath 文件路径 utf-8编码格式
 * @param tag      标签
 * @param tagSize  标签长度
 * @param l        回调函数
 */
void hid_encoder::writeFile(const std::string &filePath, const char *tag,
                            int tagSize,
                            std::weak_ptr<OnHIDWriteListener> writeListener) {

  std::lock_guard<std::mutex> lock(g_Mutex);
  if (isRunning.load()) { // 禁止重复写，必须等待业务写完
#ifdef _DEBUG
    std::cout << "HID BUSY...." << std::endl;
#endif
    std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
    if (l != nullptr) {
      l->onHIDWriteFailed(BUSY, "The HID bus busy. ");
    }
    return;
  }
  isRunning.store(true);

#ifdef _DEBUG
  std::cout << "writeFile enter...." << std::endl;
#endif

  threadPool->enqueue([this, filePath = std::move(filePath),
                       tag = std::move(tag), tagSize, writeListener] {
    std::unique_ptr<char[]> _tag(new char[tagSize]);
    if (_tag == nullptr) {
      std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
      if (l != nullptr) {
        l->onHIDWriteFailed(HID_ERR, "The file path not exists");
      }
      release();
      return;
    }
    std::fill(_tag.get(), _tag.get() + tagSize, 0);
    std::memcpy(_tag.get(), tag, tagSize);
    try {
      if (filePath.empty()) {
        std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
        if (l != nullptr) {
          l->onHIDWriteFailed(HID_ERR, "The file path not exists");
        }
        release();
        return;
      }

      // 1. 打开文件
      FILE *file = fopen(filePath.c_str(), "rb");
      if (file == NULL) {
        std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
        if (l != nullptr) {
          l->onHIDWriteFailed(HID_ERR, "Open the file error");
        }
        release();
        return;
      }

      // 读取文件的长度
      fseek(file, 0, SEEK_END);
      long contentLength = ftell(file);
      fseek(file, 0, SEEK_SET);

      // 从文件中提取后缀，转换为时间戳文件名
      size_t dotPos = filePath.rfind('.');
      if (dotPos == std::string::npos) {
        fclose(file);
        std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
        if (l != nullptr) {
          l->onHIDWriteFailed(HID_ENCODE_ERROR,
                              "The filePath must be absolute path.");
        }
        release();
        isRunning = false;
        return;
      }
      std::string extension = filePath.substr(dotPos);
      time_t timestamp = time(NULL);
      std::tm *timeInfo = std::localtime(&timestamp);
      std::ostringstream oss;
      oss << std::put_time(timeInfo,
                           "%Y%m%d%H%M%S"); // 格式化为 YYYYMMDDHHMMSS

      // 创建新文件名
      std::string fileName = oss.str() + extension;
      const char *fileNameChars = fileName.c_str();
      int fileNameLength = fileName.length();

      // 包有效长度（减去特性包、包头、附加信息）
      int requestBodyLength =
          getFileRequestBodyLength(true, fileNameLength, tagSize);

      // 计算总包个数
      long packageCount = getTotalPackCount(contentLength, requestBodyLength);

      int currentPackageIndex = 0;

      std::vector<char> dst;
      /* 读取文件数据填充到 buffer */
      std::vector<char> buffer;
      buffer.reserve(requestBodyLength);
      size_t packageLength = 0;
      while ((packageLength = fread(buffer.data(), sizeof(char),
                                    requestBodyLength, file)) > 0) {
        // 中断信号
        if (interrupt.load()) {
          release();
          fclose(file);
          std::shared_ptr<OnHIDStopDataListener> stopListener =
              stopListenerPtr.lock();
          if (stopListener != nullptr) {
            stopListener->onHIDStopData();
          }
          return;
        }

        // 1. 填充头
        fillFileHead(dst, contentLength, packageLength, fileNameLength);
        // 2. 拷贝文件名
        dst.insert(dst.end(), fileNameChars, fileNameChars + fileNameLength);

        // 3. 拷贝标签内容
        dst.push_back((char)tagSize);
        dst.push_back((char)(tagSize >> 8));
        if (_tag != nullptr) {
          dst.insert(dst.end(), _tag.get(), _tag.get() + tagSize);
        }

        // 4. 拷贝文件内容
        dst.insert(dst.end(), buffer.data(), buffer.data() + packageLength);

        // 5. 计算并填充 CRC
        int startIndex =
            getFilePackageContentStart(true, fileNameLength, tagSize);
        std::vector<char> crc(dst.begin() + startIndex,
                              dst.begin() + startIndex + packageLength);
        uint16_t crcIbm =
            crc16_ibm1((uint8_t *)crc.data(), (uint16_t)crc.size());
        dst.push_back(crcIbm);
        dst.push_back(crcIbm >> 8);

        // 魔数
        dst.push_back(JING_CHAR);
        dst.push_back(YUAN_YU_CHAR);
        dst.push_back(YUAN_YU_CHAR);

        // 调用写数据接口
        if (ALLOW_LENGTH - dst.size() > 0) {
          dst.insert(dst.end(), ALLOW_LENGTH - dst.size(), 0);
        }

        if (this->write(dst.data(), ALLOW_LENGTH) == -1) {
          release();
          fclose(file);
          return;
        }

        currentPackageIndex++;
        std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
        if (l != nullptr) {
          l->onHIDWriteResult(currentPackageIndex, packageCount,
                              currentPackageIndex >= packageCount);
        }
        dst.resize(0);
      }
      release();
      fclose(file);
    } catch (...) {
      release();
      std::shared_ptr<OnHIDWriteListener> l = writeListener.lock();
      if (l != nullptr) {
        l->onHIDWriteFailed(HID_WRITE_ERROR, "Write file error");
      }
    }
    release();
#ifdef _DEBUG
    std::cout << "writeDataSync exit...." << std::endl;
#endif
  });
}

/**
 *  hid 总线写数据
 * @brief hid_encoder::write
 * @param data
 * @param length
 * @return
 */
int hid_encoder::write(char *data, int length) {
  if (hidInterface) {
    return hidInterface->write(data, length);
  }

  return -1;
}

/**
 * 停止发送数据
 * @brief hid_encoder::stop
 * @param l
 * @return
 */
bool hid_encoder::stop(
    std::weak_ptr<OnHIDStopDataListener> onStopDataListener) {
  std::lock_guard<std::mutex> lock(m_Mutex_Var);
  if (isRunning) {
    this->stopListenerPtr = onStopDataListener;
    interrupt = true;
    return false;
  }
  return true;
}

/**
 * 取消任务
 * @brief hid_encoder::cancel
 * @return
 */
void hid_encoder::cancel() {
  std::lock_guard<std::mutex> lock(m_Mutex_Var);
  interrupt = false;
}

bool hid_encoder::isRun() const { return this->isRunning.load(); }

void hid_encoder::release() {
  isRunning.store(false);
  interrupt.store(false);
}

/**
 * 取消任务，此时文件时不完整的。
 */
void hid_encoder::cancelRandomFile() {
  std::lock_guard<std::mutex> lock(m_Mutex_Var);
  if (state == PAUSED || state == STARTED) {
    mRandomTaskRunning = false;
    state = CANCEL;
#ifdef _DEBUG
    std::cout << "任务即将进入取消状态...." << std::endl;
#endif
  }
}

/**
 * 停止发送随机文件，此时文件不完整的，需要等待写重传包
 */
void hid_encoder::stopRandomFile() {
  std::lock_guard<std::mutex> lock(m_Mutex_Var);
  if (state == PAUSED || state == STARTED) {
    state = STOP;
#ifdef _DEBUG
    std::cout << "任务即将进入停止状态...." << std::endl;
#endif
  }
}

/**
 * 暂停任务
 */
void hid_encoder::pause() {
  std::lock_guard<std::mutex> lock(m_Mutex_Var);
  if (state == STARTED) {
    flag = true;
    state = PAUSE; // 通知任务进入暂停状态
#ifdef _DEBUG
    std::cout << "任务进入暂停状态...." << std::endl;
#endif
  }
}

/**
 *  恢复任务
 */
void hid_encoder::resume() {
  std::lock_guard<std::mutex> lock(m_Mutex_Var);
  if (state == PAUSED) {
    state = RESUMED;
#ifdef _DEBUG
    std::cout << "恢复任务...." << std::endl;
#endif
  }
}
